#include <WiFi.h>
#include <PubSubClient.h>

// Wi-Fi网络名称和密码
const char* ssid = "wjs";
const char* password = "03070920";

// MQTT代理地址和端口
const char* mqtt_server = "broker.emqx.io";
const int mqtt_port = 1883;

// 按键引脚
const int buttonPin = 2; // 假设按键连接到GPIO2

// 创建WiFi和MQTT客户端对象
WiFiClient espClient;
PubSubClient client(espClient);

// 按键状态变量
int lastButtonState = HIGH; // 按键初始状态为未按下

void setup() {
  // 初始化串口通信
  Serial.begin(115200);

  // 初始化按键引脚
  pinMode(buttonPin, INPUT_PULLUP);

  // 连接到Wi-Fi网络
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);

  // 等待连接成功
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  // 连接成功后，打印IP地址
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  // 设置MQTT代理地址和端口
  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(callback); // 设置回调函数
}

void loop() {
  // 检查MQTT客户端是否连接，如果没有连接则尝试重新连接
  if (!client.connected()) {
    reconnect();
  }
  client.loop(); // 处理MQTT网络事件，包括心跳

  // 读取按键状态
  int buttonState = digitalRead(buttonPin);

  // 如果按键被按下且之前未按下，则发送消息
  if (buttonState == LOW && lastButtonState == HIGH) {
    sendIntroduction();
    lastButtonState = LOW; // 更新按键状态
  } else if (buttonState == HIGH) {
    lastButtonState = HIGH; // 更新按键状态
  }
}

// 重新连接到MQTT代理
void reconnect() {
  // 循环直到连接成功
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // 生成唯一的客户端ID
    char clientId[24];
    snprintf(clientId, sizeof(clientId), "ESP32Client_%lu", millis());
    // 尝试连接到MQTT代理
    if (client.connect(clientId)) {
      Serial.println("connected");
      // 订阅某个主题
      client.subscribe("emqx/AIAgriculture");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 10 seconds");
      // 等待10秒后重试
      delay(10000);
    }
  }
}

// 处理接收到的消息
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}

// 发送自我介绍消息
void sendIntroduction() {
  const char* introduction = "Hello, I am Jiashuo Wang";
  if (client.publish("emqx/AIAgriculture", introduction)) {
    Serial.println("Introduction sent.");
  } else {
    Serial.println("Failed to send introduction.");
  }
}